package jus.poc.prodcons.v3;

import java.util.Date;
import jus.poc.prodcons.*;

/**
 * ProdCons gère les échanges à partir des buffers
 *
 * @author Nunes Thomas <nds.thomas@gmail.com>
 * @author Feng Xu <fengxu1989@gmail.com>
 */
public class ProdCons implements Tampon {

    protected int nbBuffer;
    protected Message buffers[];
    protected int enAttente;
    protected int indice;
    protected Semaphore mutex = new Semaphore(1);
    protected Semaphore attente = new Semaphore(0);
    protected Semaphore ecrit;

    public ProdCons(int nbBuffer) {
        this.nbBuffer = nbBuffer;
        buffers = new Message[nbBuffer];
        enAttente = 0;
        indice = 0;
        ecrit = new Semaphore(nbBuffer);
    }

    @Override
    public int enAttente() {
        return enAttente;
    }

    @Override
    public Message get(_Consommateur arg0) throws Exception,
            InterruptedException {
        Message m;
        attente.P();
        mutex.P();
        m = buffers[mod((indice - enAttente), nbBuffer)];
        ((MessageX) m).setRecu(new Date());
        ((Consommateur) arg0).retraitMessage(m);

        enAttente--;
        ecrit.V();

        mutex.V();
        return m;
    }

    @Override
    public void put(_Producteur arg0, Message arg1) throws Exception,
            InterruptedException {
        ecrit.P();
        mutex.P();
        ((MessageX) arg1).setDate(new Date());
        ((Producteur) arg0).deposerMessage(arg1);

        buffers[indice] = arg1;
        indice = (indice + 1) % nbBuffer;
        enAttente++;
        attente.V();
        mutex.V();
    }

    @Override
    public int taille() {
        return nbBuffer;
    }

    private int mod(int a, int b) {
        int res = a % b;
        if (res < 0 && b > 0) {
            res += b;
        }
        return res;
    }
}
